package myProject.gwt.client.dynamicTable;

import java.util.HashSet;

import myProject.gwt.client.DebugPanel;
import myProject.gwt.client.simpleTable.AbstractTable;
import myProject.gwt.client.simpleTable.Header;
import myProject.gwt.client.simpleTable.HeaderCell;
import myProject.gwt.client.simpleTable.IHeader;
import myProject.gwt.client.simpleTable.IHeaderCell;
import myProject.gwt.client.simpleTable.IHeaderListener;

import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;

public class DynamicTable extends AbstractTable{

	private SimplePanel content = new SimplePanel();
	private Element contentElement;
	private HashSet<Integer> cache = new HashSet<Integer>();
	private Header header;
	private int columnCount;
	private int recordCount;
	private boolean cacheCells;
	private boolean drawSummary;
	
	public DynamicTable(String[] headerCaptions, int recordCount){
		//this.add(content);
		//this.setStylePrimaryName("scroll");
		content.setStylePrimaryName("container");
		contentElement = content.getElement();
		long time = System.currentTimeMillis();
		createHeader(headerCaptions);
		this.columnCount = headerCaptions.length;
		this.recordCount = recordCount;
		//Window.alert(""+(System.currentTimeMillis() - time));		
		//fullRepaint();
		resizeContent();
		drawRows(0, 0, Math.min(30, recordCount-1), 0, Math.min(10, columnCount-1));
		init();
	}
	
	
	
	protected void onScroll() {
		super.onScroll();
		if(!isFakeScrollBar()) repaint();
	}
		
	protected void onBeforeScroll() {
		super.onBeforeScroll();
		if(isFakeScrollBar()) repaint();
	}



	private void resizeContent(){
		int width = 0;
		for(int i=0; i < columnCount; i++){
			width += getColumnWidth(i);
		}
		
		int height = 21 * recordCount;
		
		content.setPixelSize(width, height);
	}
	
	private void repaint(){
		int sc = getScrollPostion();
		int startRow = sc / 21;
		int endRow = Math.min(startRow + (this.getOffsetHeight() / 21), recordCount);
		
		int startCol = 0;
		int endCol = 0;
		int hsc = getHorizontalScrollPostion();

		int startLeft = 0;		
		for(int i=0; i<columnCount; i++){
			int w = getColumnWidth(i);			
			if(startLeft+w >= hsc){
				startCol = i;
				break;
			}
			startLeft += w;
		}
		
		DebugPanel.addText("sl "+startLeft+", hsc "+hsc);
		
		int endLeft = 0;
		int width = this.getOffsetWidth();
		endCol = columnCount-1;
		for(int i=startCol; i<columnCount ; i++){
			endLeft += getColumnWidth(i);
			if(endLeft >= width){
				endCol = i;
				break;
			}
		}
		 		
		DebugPanel.addText("("+startRow+"-"+endRow+")x("+startCol+"-"+endCol+")");
		drawRows(startLeft, startRow, endRow, startCol, endCol);
	}
	
	
	private void drawRows(int startLeft, int startRow, int endRow, int startCol, int endCol){
		StringBuilder sb = new StringBuilder();

		for(int row=startRow; row<=endRow; row++){
			int left = startLeft;
			for(int col=startCol; col<=endCol; col++){				
				int colWidth = getColumnWidth(col); 
				
				if(cacheCells){
					int key = row*65536+col;					
					if(cache.contains(key)){
						left += colWidth;
						continue;
					}
					cache.add(key);
				}
				
				int top = row*21;
				String className = "box";
				if((row % 2) == 0) className += " evenRow";
				else className += " oddRow";
				
				String text = row+"/"+col;
				//String text = ""+System.currentTimeMillis();
				
				sb.append(getCellHtml(className, left, top, colWidth, text));
				
				DebugPanel.addText(row+"/"+col);
				left += colWidth;
			}
		}

		if(drawSummary){
			sb.append(drawSummaryRow(startLeft, startRow, endRow, startCol, endCol));
			sb.append(drawSummaryColumn(startLeft, startRow, endRow, startCol, endCol));
			sb.append(drawSummaryCell(startLeft, startRow, endRow, startCol, endCol));
		}
		
		//sb.append(getCellHtml("box summary", 0, getScrollPostion()+this.getOffsetHeight()-90, 300, "SUMMARY"));
		//sb.append(getCellHtml("box summary", getHorizontalScrollPostion()+this.getOffsetWidth()-200, getScrollPostion(), 300, "SUMMARY"));
		
		if(cacheCells){
			Element el = DOM.createDiv();
			el.setInnerHTML(sb.toString());
			contentElement.appendChild(el);	
		}else{
			contentElement.setInnerHTML(sb.toString());
		}
		
	}
	
	private String drawSummaryRow(int startLeft, int startRow, int endRow, int startCol, int endCol){
		StringBuilder sb = new StringBuilder();
		int left = startLeft;
		int top = Math.min(getScrollPostion()+this.getOffsetHeight()-93, recordCount*21);
		for(int col=startCol; col<=endCol; col++){	
			int colWidth = getColumnWidth(col); 
			sb.append(getCellHtml("box summary", left, top, colWidth, "SUMMARY"));
			left += colWidth;
		}
		return sb.toString();
	}
	
	private String drawSummaryColumn(int startLeft, int startRow, int endRow, int startCol, int endCol){
		StringBuilder sb = new StringBuilder();
		int left = Math.min(getHorizontalScrollPostion()+this.getOffsetWidth()-150, getColumnWidth(0, columnCount-1));
		//int oh = Math.max(this.getOffsetHeight(), Integer.MAX_VALUE);
		int top = getScrollPostion()-(getScrollPostion() % 21);
		int colWidth = getColumnWidth(endCol);
		for(int row=startRow; row<endRow; row++){
			sb.append(getCellHtml("box summary", left, top, colWidth, "SUMMARY"));
			top += 21;
		}
		return sb.toString();
	}
	
	private String drawSummaryCell(int startLeft, int startRow, int endRow, int startCol, int endCol){

		int left = Math.min(getHorizontalScrollPostion()+this.getOffsetWidth()-150, getColumnWidth(0, columnCount-1));
		int top = Math.min(getScrollPostion()+this.getOffsetHeight()-93, recordCount*21);
		int colWidth = getColumnWidth(endCol);
		return getCellHtml("box summary summaryCell", left, top, colWidth, "SUMMARY");
	}
	
	private int getColumnWidth(int startCol, int endCol){
		int w = 0;
		for(int i=0; i<=endCol; i++) w += getColumnWidth(i);
		return w;
	}
	
	private String getCellHtml(String className, int left, int top, int width, String text){
		return "<div class=\""+className+"\" style=\"left: "+left+"px; top: "+top+"px; width:"+width+"px\">"+text+"</div>";
	}

	@Override
	protected Widget getContent() {
		return content;
	}

	@Override
	protected IHeader getHeader() {
		return header;
	}
	
	private void createHeader(String[] headerCaptions){
		
		header = new Header();
		for(int col=0; col < headerCaptions.length; col++){

			HeaderCell hc = new HeaderCell(col, headerCaptions[col]);
			hc.setWidth(100);
			header.addHeaderCell(hc);
		}
		
		header.setHeaderListener(new IHeaderListener(){
			@Override
			public void headerResized(IHeaderCell headerCell) {
				resizeColumn(headerCell.getColumnIndex(), headerCell.getWidth());
			}

			@Override
			public void headerResizing(IHeaderCell headerCell) {
				//resizeColumn(headerCell.getColumnIndex(), headerCell.getWidth());				
			}
		});
	}
	
	public void fullRepaint(){
		cache.clear();
		contentElement.setInnerHTML("");
		resizeContent();
		repaint();	
	}
	
	private void resizeColumn(int columnIndex, int width) {
		//Element el = DOM.getElementById("resizeCell"+columnIndex);
		//el.getStyle().setPropertyPx("width", width);
		resizeContent();
		fullRepaint();
	}



	public void setCacheCells(boolean cacheCells) {
		this.cacheCells = cacheCells;
	}



	public void setDrawSummary(boolean drawSummary) {
		this.drawSummary = drawSummary;
	}


	

	
	
}
